﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace Inovout.Cloud.Identity.QuickStarts.Controllers
{
    
    [AllowAnonymous]
    public class AccountController : Controller
    {
       
        static AccountController()
        {
            ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback);
        }

        private static bool  RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
        public ActionResult SignIn(string returnUrl)
        {
            ViewBag.Providers = Newtonsoft.Json.JsonConvert.DeserializeObject(GetProvides());
            string redirect_uri = this.Url.Encode(GetRedirectUri(returnUrl).AbsoluteUri);
            //ViewBag.SignInUrl = @"http://localhost:10000/OAuthd/Authorize?provider=inovout&client_id=eb64a2a9ab054af49a0fba5446444145&redirect_uri=" + redirect_uri + "&response_type=code";
            ViewBag.RedirectUrl = @"&client_id=" + System.Configuration.ConfigurationManager.AppSettings["ClientId"] + "&redirect_uri=" + redirect_uri;
            return View();
        }

        private string GetProvides()
        {
            var ProvidersServiceEndpoint = System.Configuration.ConfigurationManager.AppSettings["ProvidersServiceEndpoint"];
            var builder = new UriBuilder(ProvidersServiceEndpoint);
            HttpClient httpClient = new HttpClient();
            var result = httpClient.GetAsync(builder.Uri);
            var providers = result.Result.Content.ReadAsStringAsync().Result;
            return providers;
        }

        private Uri GetRedirectUri(string returnUrl)
        {
            return new Uri(this.Request.Url, Url.Action("ExtensionalSignInCallback", "Account", new { returnUrl = returnUrl }));
        }

        public ActionResult ExtensionalSignInCallback(string returnUrl)
        {

            var token = QueryAccessToken(GetRedirectUri(returnUrl), this.Request.QueryString["code"]);
            if (!string.IsNullOrEmpty(token))
            {
                var membership = GetUserData(token);
                SignIn(membership["username"], membership, false);
            }

            if (!string.IsNullOrEmpty(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return Redirect("~/");
            }

        }

        private void SignIn(string userName, IDictionary<string, string> membership, bool createPersistentCookie)
        {
            string userData = Newtonsoft.Json.JsonConvert.SerializeObject(membership);
            FormsAuthenticationTicket formsAuthenticationTicket = new FormsAuthenticationTicket(2,
                userName, DateTime.Now, DateTime.Now.Add(FormsAuthentication.Timeout),
                                 createPersistentCookie, userData);

            string encryptFormsAuthenticationTicket = FormsAuthentication.Encrypt(formsAuthenticationTicket);

            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptFormsAuthenticationTicket)
            {
                HttpOnly = true,
                Secure = FormsAuthentication.RequireSSL,
                Path = FormsAuthentication.FormsCookiePath
            };
            if (createPersistentCookie)
            {
                cookie.Expires = formsAuthenticationTicket.Expiration;

            }
            cookie.Domain = FormsAuthentication.CookieDomain;
            HttpContext.Response.Cookies.Add(cookie);

        }


        protected string QueryAccessToken(Uri returnUrl, string authorizationCode)
        {
            var clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];
            var clientSecret = System.Configuration.ConfigurationManager.AppSettings["ClientSecret"];
            var TokenServiceEndpoint = System.Configuration.ConfigurationManager.AppSettings["TokenEndpoint"];
            HttpClient httpClient = new HttpClient();
            var content = new FormUrlEncodedContent(new[] 
            {
                new KeyValuePair<string, string>("client_id", clientId),
                new KeyValuePair<string, string>("redirect_uri", returnUrl.AbsoluteUri),
                new KeyValuePair<string, string>("client_secret", clientSecret),
                new KeyValuePair<string, string>("code", authorizationCode),
                new KeyValuePair<string,string>("grant_type","authorization_code")
            });
            var result = httpClient.PostAsync(TokenServiceEndpoint, content);
            var tokenObject = result.Result.Content.ReadAsAsync<Dictionary<string, string>>().Result;
            try {
                return tokenObject["access_token"];
            }catch(Exception ex){
                return null;
            }
           
        }


        protected IDictionary<string, string> GetUserData(string accessToken)
        {
            var UserDataServiceEndpoint = System.Configuration.ConfigurationManager.AppSettings["UserDataServiceEndpoint"];
            var builder = new UriBuilder(UserDataServiceEndpoint);
            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",
                accessToken);
            httpClient.DefaultRequestHeaders.Add("Accept","application/json");
            var result = httpClient.GetAsync(builder.Uri);
            var userObject = result.Result.Content.ReadAsAsync<Dictionary<string, string>>().Result;
            //var userObject = result.Result.Content.ReadAsStringAsync().Result;
            //var tokenJson = JObject.Parse(tokenString);
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            foreach (var dic in dictionary)
            {
                dictionary.Add(dic.Key, userObject[dic.Value].ToString());
            }
            dictionary.Add("id", userObject["user_identifier"]);
            dictionary.Add("username", userObject["name"]);
            dictionary.Add("email", userObject["email"]);
            return dictionary;
        }



    }
}